/*
Copyright 2021 LuJun

Permission is hereby granted, free of charge, to any person obtaining a copy 
of this software and associated documentation files (the "Software"), to deal 
in the Software without restriction, including without limitation the rights 
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 
copies of the Software, and to permit persons to whom the Software is furnished 
to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in 
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/

import { _decorator, Component, Node } from 'cc';
const { ccclass, property, menu } = _decorator;
import { UICanvas, uiMgr } from './ui-manager';

const TAG = 'lcc/ui/ui-base.ts';

/**
 * UI动画类型
 */
export enum UIAnimationType {
    /**
     * 打开
     */
    OPEN,

    /**
     * 关闭
     */
    CLOSE
}

/**
 * UI动画接口
 */
export interface UIAnimationInterface {
    /**
     * 动画播放
     *
     * @param aType 动画类型
     */
    play: (aType: UIAnimationType) => Promise<any>;
}

/**
 * @zh
 * UI基类
 */
@ccclass('lcc/ui/UIBase')
export class UIBase extends Component {
    /**
     * @zh
     * 根节点
     */
    private _rootNode: Node = null!;

    /**
     * @zh
     * 获得根节点
     */
    get rootNode() {
        return this._rootNode;
    }

    /**
     * @zh
     * UI名称
     */
    private _uiName: string = null!;

    /**
     * @zh
     * 获得UI名称
     */
    get uiName(): string {
        return this._uiName;
    }

    /**
     * @zh
     * 画布对象
     */
    private _canvas: UICanvas = null!;

    /**
     * @zh
     * 获得画布对象
     */
    get canvas() {
        return this._canvas;
    }

    /**
     * @zh
     * 固定优先级
     */
    private _fixedPriority: number = null!;

    /**
     * @zh
     * 获得固定优先级
     */
    get fixedPriority(): number {
        return this._fixedPriority;
    }

    /**
     * @zh
     * UI动画接口
     */
    private _uiAnimation: UIAnimationInterface = null!;

    /**
     * @zh
     * 配置UI
     *
     * @param rootNode 根节点
     * @param canvas 画布对象
     * @param uiName UI名称
     */
    configUI(rootNode: Node, canvas: UICanvas, uiName: string) {
        this._rootNode = rootNode;
        this._canvas = canvas;
        this._uiName = uiName;
    }

    /**
     * @zh
     * 设置是否激活
     *
     * @param active - 是否激活
     */
    setActive(active: boolean) {
        this._rootNode.active = active;
    }

    /**
     * @zh
     * 设置固定优先级
     *
     * @param priority - 优先级
     */
    setFixedPriority(priority: number) {
        this._fixedPriority = priority;
    }

    /**
     * 设置UI动画
     *
     * @param uiAnimation UI动画
     */
    setUIAnimation(uiAnimation: UIAnimationInterface) {
        this._uiAnimation = uiAnimation;
    }

    /**
     * @zh
     * 关闭当前UI
     */
    closeSelf(release: boolean = false) {
        return uiMgr.closeUI(this.uiName, release);
    }

    /**
     * @zh
     * 播放UI动画
     *
     * @param aType 动画类型
     */
    async playUIAnimation(aType: UIAnimationType) {
        if (this._uiAnimation) {
            await this._uiAnimation.play(aType);
        }
    }

    /**
     * @zh
     * UI创建回调，子类中可以重写这个函数
     */
    onUICreate() {}

    /**
     * @zh
     * UI打开回调，子类中可以重写这个函数
     *
     * @param args - 打开参数
     */
    onOpen(...args: any[]): any {}

    /**
     * @zh
     * UI关闭回调，子类中可以重写这个函数
     */
    onClose() {}

    /**
     * @zh
     * UI释放回调，子类中可以重写这个函数
     */
    onUIRelease() {}

    /**
     * @zh
     * 当改变当前UI最前面，子类中可以重写这个函数
     *
     * @param isFront 当前UI是否在最前面
     */
    onFrontState(isFront: boolean) {}

    /**
     * @zh
     * 当按键按下，子类中可以重写这个函数
     */
    onKeyPressed(keyCode: string) {
        return false;
    }

    /**
     * @zh
     * 当保存UI时，返回UI数据<br/>
     * 一般用于push UI时，前一个UI需要保存数据；当pop UI时，会使用此数据调用onOpen以恢复UI
     * 特别注意，如果是数组会在恢复UI时进行解包操作
     */
    onSaveUI() {
        return null;
    }

    /**
     * @zh
     * 如果UI不通过管理器,在start函数打开
     */
    start() {
        if (!this._rootNode) {
            this.onUICreate();
            this.onOpen();
        }
    }

    /**
     * @zh
     * 如果UI不通过管理器,在onDestroy函数关闭
     */
    onDestroy() {
        if (!this._rootNode) {
            this.onClose();
            this.onUIRelease();
        }
    }
}
